iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
Mobile Development

Flutter - 從 Packages & Plugins 掌握原生系列 第 16

Day16 開發套件 - 實作EventChannel

  • 分享至 

  • xImage
  •  

使用上跟MethodChannel類似,EventChannel即為MethodChannelStream的結合

Flutter 端:

首先同樣先建立Channel並指定名稱(記得所有通道名稱都不能重複),然後要對Native 端傳遞來的訊息進行監聽,通過EventChannel調用receiveBroadcastStream()來取得一個Stream物件,後續通過在Stream中新增監聽來完成對 Native 端訊息的接收等操作

lib/batterylevel.dart

這邊建立一個EvnetChannel來取得Native 端一個骰子持續搖出來的數字,並建立一個取得骰子訊息的Stream物件方法

  static const EventChannel _eventChannel = const EventChannel('dice_number');
 
	static Stream<int> get getRandomNumberStream {
    return _eventChannel.receiveBroadcastStream().cast();
  }

Native 端(Android):

android/.../BatterylevelPlugin.kt

這邊一樣要設置好EvnetChannel,指定名稱(需要與Flutter 端使用的EvnetChannel名稱相對應),並通過EvnetChannel呼叫setStreamHandler來註冊一個MessageHandler來接收此通道訊息,這邊不像預設的範例直接讓BatterylevelPlugin實現setStreamHandler的接口,我們將接口的實現拉出來一個類別來實作,這樣把實現接口的邏輯拉出去實作,BatterylevelPlugin才不會在功能變多時變得太複雜

所以建立一個RandomNumberStreamHandler.kt 來實現接口,這邊每一秒骰一次骰子並將結果回傳至Flutter 端

class RandomNumberStreamHandler : EventChannel.StreamHandler {
    private var sink: EventChannel.EventSink? = null
    private var handler: Handler? = null

    private val runnable = Runnable {
        sendNewRandomNumber()
    }

    private fun sendNewRandomNumber() {
        val randomNumber = (1..6).random()
        sink?.success(randomNumber)
        handler?.postDelayed(runnable, 1000)
    }

    override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
        sink = events
        handler = Handler()
        handler?.post(runnable)
    }

    override fun onCancel(arguments: Any?) {
        sink = null
        handler?.removeCallbacks(runnable)
    }
}

BatterylevelPlugin.kt 加上:

    private lateinit var eventChannel: EventChannel

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        //Added
        eventChannel = EventChannel(flutterPluginBinding.binaryMessenger, "dice_number")
        eventChannel.setStreamHandler(RandomNumberStreamHandler())
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        //Added
        eventChannel.setStreamHandler(null)
    }

Native 端(iOS):

一樣可以把setStreamHandler的接口實現的邏輯拉出去實作,同樣建立一個RandomNumberStreamHandler.swift 來實現接口,每一秒骰一次骰子並將結果回傳至Flutter 端

ios/Classes/RandomNumberStreamHandler.swift

import Foundation
import Flutter

class RandomNumberStreamHandler: NSObject, FlutterStreamHandler{
    var sink: FlutterEventSink?
    var timer: Timer?
    
    @objc func sendNewRandomNumber() {
        guard let sink = sink else { return }
        
        let randomNumber = Int.random(in: 1..<7)
        sink(randomNumber)
    }
    
    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        sink = events
        timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(sendNewRandomNumber), userInfo: nil, repeats: true)
        return nil
    }
    
    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        sink = nil
        timer?.invalidate()
        return nil
    }
}

ios/Classes/SwiftBatterylevelPlugin.swift

import Flutter
import UIKit

public class SwiftBatterylevelPlugin: NSObject, FlutterPlugin {
    public static func register(with registrar: FlutterPluginRegistrar) {
				//Added
        let eventChannel = FlutterEventChannel(name: "dice_number", binaryMessenger: registrar.messenger())
        let randomNumberStreamHandler = RandomNumberStreamHandler()
        eventChannel.setStreamHandler(randomNumberStreamHandler)
    }
}

上一篇
Day15 開發套件 - 實作MethodChannel
下一篇
Day17 開發套件 - 實作BasicMessageChannel
系列文
Flutter - 從 Packages & Plugins 掌握原生30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言